using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using Acms.SqlDal;
using System.Xml;

namespace Acms.Bll
{
    public class UserPostUpload : BaseItem
    {
        protected UserPostUpload() : base() { }
        protected UserPostUpload(Hashtable table) : base(table) { }
        protected UserPostUpload(Hashtable table, List<UserPostUpload> collection) : base(table, collection) { }
        protected UserPostUpload(Hashtable table, ICollection collection) : base(table, collection) { }

        public static UserPostUpload CreateInstance(int userId, int postId, System.Net.IPAddress ipAddress)
        {
            UserPostUpload tmp = new UserPostUpload();
            tmp.userId = userId;
            tmp.postId = postId;
            tmp.ipAddress = ipAddress;
            return tmp;
        }


        protected override Base CreateDal()
        {
            return new UserPostUploadDal();
        }

        bool usingFileTransaction;
        public new void Update()
        {
            bool commitTran = filesToSave != null && this.TransactionKey == Guid.Empty;
            if (commitTran)
            {
                BeginTransaction();
            }
            try
            {
                base.Update();
                UpdateFiles();
                if(commitTran)
                    CommitTransaction();
            }
            catch
            {
                try
                {
                    if (commitTran)
                        RollbackTransaction();

                }
                catch
                {
                }
                throw;
            }
        }

        public void Update(File.FileTypes fileType, System.Web.HttpPostedFile httpPostedFile, byte[] fileData)
        {
            //begin transaction if one hasn been created
            bool commitTran = this.TransactionKey == Guid.Empty;
            if (commitTran)
            {
                BeginTransaction();
            }

            try
            {
                File tmp = File.CreateInstance(fileType, httpPostedFile, fileData);
                tmp.UseTransaction(this.TransactionKey);
                tmp.Update();

                this.fileId = tmp.Id;
                base.Update();

                UpdateFiles();

                if (commitTran)
                    CommitTransaction();
            }
            catch
            {
                try
                {
                    if (commitTran)
                        RollbackTransaction();

                }
                catch
                {
                }
                throw;
            }
        }

        public void Update(File.FileTypes fileType, string fileName, string contentType, int fileLength, System.IO.Stream fileStream)
        {
            //begin transaction if one hasn been created
            bool commitTran = this.TransactionKey == Guid.Empty;
            if (commitTran)
            {
                BeginTransaction();
            }

            try
            {
                File tmp = File.CreateInstance(fileType, fileName, contentType, fileLength, fileStream);
                tmp.UseTransaction(this.TransactionKey);
                tmp.Update();

                this.fileId = tmp.Id;
                base.Update();

                UpdateFiles();

                if (commitTran)
                    CommitTransaction();
            }
            catch
            {
                try
                {
                    if (commitTran)
                        RollbackTransaction();

                }
                catch
                {
                }
                throw;
            }
        }

        private void UpdateFiles()
        {
            if (filesToSave != null && this.Id > 0)
            {
                foreach (string key in filesToSave.Keys)
                {
                    UserPostUploadFile file = GetFile(key);
                    if (file == null)
                    {
                        file = UserPostUploadFile.CreateInstance(this.Id, key);
                    }

                    File tmp = null;
                    if (filesToSave[key].Length == 3)
                    {
                        File.FileTypes fileType = (File.FileTypes)filesToSave[key][0];
                        System.Web.HttpPostedFile httpPostedFile = (System.Web.HttpPostedFile)filesToSave[key][1];
                        byte[] fileData = (byte[])filesToSave[key][2];
                        //create file and set file id in UserPostUploadFile
                        tmp = File.CreateInstance(fileType, httpPostedFile, fileData);
                    }
                    else if (filesToSave[key].Length == 5)
                    {
                        File.FileTypes fileType = (File.FileTypes)filesToSave[key][0];
                        string fileName = (string)filesToSave[key][1];
                        string contentType = (string)filesToSave[key][2];
                        int fileLength = (int)filesToSave[key][3];
                        System.IO.Stream fileStream = (System.IO.Stream)filesToSave[key][4];
                        //create file and set file id in UserPostUploadFile
                        tmp = File.CreateInstance(fileType, fileName, contentType, fileLength, fileStream);
                    }
                    else
                    {
                        throw new ApplicationException(string.Format("Invalid File Data Array. Expecting length of 3 or 5 actually '{0}'", filesToSave[key].Length.ToString()));
                    }
                    if (tmp != null)
                    {
                        tmp.UseTransaction(this.TransactionKey);
                        tmp.Update();
                       file.UseTransaction(this.TransactionKey);
                        file.FileId = tmp.Id;
                        file.Update();
                    }
                }
                filesToSave = null;
                files = null;
            }   
        }

        protected override object SaveChanges(ref object concurencyId, Base dal)
        {
            if (IsNewRecord)
            {
                created = DateTime.Now;
            }
            
            XmlDocument tmp = new XmlDocument();
            tmp.AppendChild(tmp.CreateElement("textFields"));
            foreach(string key in textFields.Keys)
            {
                XmlNode node = tmp.CreateElement(key);
                node.AppendChild(tmp.CreateTextNode(textFields[key]));
                tmp.DocumentElement.AppendChild(node);
            }

            ((UserPostUploadDal)dal).Update(ref id, userId, ref userName, postId, fileId, title, comment, ipAddress, reviewed, reported, suspended, created, ref averageVote, tmp, ref concurencyId);
            return id;
        }

        public new void Delete()
        {
            base.Delete();
        }

        protected override void DeleteRecord(object concurencyId, Base dal)
        {
            //begin transaction
            if (this.TransactionKey == Guid.Empty)
            {
                usingFileTransaction = true;
                BeginTransaction(dal);
            }
            var tmp = FileInfo.GetById(this.FileId);
            ((UserPostUploadDal)dal).Delete(id, concurencyId);
            if (tmp != null)
            {
                tmp.UseTransaction(this.TransactionKey);
                tmp.Delete();
            }
            if (usingFileTransaction)
            {
                CommitTransaction(dal);
            }
        }

        private static UserPostUpload Get(Hashtable table)
        {
            if (table != null)
            {
                return new UserPostUpload(table);
            }
            else
            {
                return null;
            }
        }

        private static List<UserPostUpload> Get(Hashtable[] tables)
        {
            if (tables != null)
            {
                List<UserPostUpload> tmp = new List<UserPostUpload>();
                foreach (Hashtable table in tables)
                {
                    tmp.Add(new UserPostUpload(table, tmp));
                }
                return tmp;
            }
            else
            {
                return null;
            }
        }

        public static UserPostUpload GetById(int id)
        {
            UserPostUploadDal dal = new UserPostUploadDal();
            return Get(dal.GetById(id));
        }

        public static List<UserPostUpload> GetAllByUserIdAndPostId(int userId, int postId)
        {
            UserPostUploadDal dal = new UserPostUploadDal();
            return Get(dal.GetAllByUserIdAndPostId(userId, postId));
        }

        public static List<UserPostUpload> GetAllByPostId(int postId)
        {
            UserPostUploadDal dal = new UserPostUploadDal();
            return Get(dal.GetAllByPostId(postId));
        }

        protected override void Load(Hashtable table)
        {
            id = (int)table[UserPostUploadDal.Fields.Id];
            userId = (int)table[UserPostUploadDal.Fields.UserId];
            userName = (string)table[UserPostUploadDal.Fields.UserName];
            postId = (int)table[UserPostUploadDal.Fields.PostId];
            fileId = (int)table[UserPostUploadDal.Fields.FileId];
            title = (string)table[UserPostUploadDal.Fields.Title];
            comment = (string)table[UserPostUploadDal.Fields.Comment];
            ipAddress = (System.Net.IPAddress)table[UserPostUploadDal.Fields.IPAddress];
            reviewed = (bool)table[UserPostUploadDal.Fields.Reviewed];
            reported = (bool)table[UserPostUploadDal.Fields.Reported];
            suspended = (bool)table[UserPostUploadDal.Fields.Suspended];
            created = (DateTime)table[UserPostUploadDal.Fields.Created];
            averageVote = (decimal)table[UserPostUploadDal.Fields.AverageVote];
            System.Xml.XmlDocument tmp = (System.Xml.XmlDocument)table[UserPostUploadDal.Fields.TextFields];
            if(tmp != null && tmp.DocumentElement != null)
            {
                textFields = new Dictionary<string, string>();
                foreach (XmlNode node in tmp.DocumentElement.ChildNodes)
                {
                    textFields.Add(node.Name, node.InnerText);
                }
            }
        }

        private int id;
        public int Id
        {
            get { return id; }
        }

        private int userId;
        public int UserId
        {
            get { return userId; }
        }

        private string userName;
        public string UserName
        {
            get { return userName; }
        }

        private int postId;
        public int PostId
        {
            get { return postId; }
        }
	

        private int fileId;
        public int FileId
        {
            get { return fileId; }
        }
	

        private string title;
        public string Title
        {
            get { return title; }
            set { title = value; }
        }

        private string comment;
        public string Comment
        {
            get { return comment; }
            set { comment = value; }
        }

        private System.Net.IPAddress ipAddress;
        public System.Net.IPAddress IPAddress
        {
            get { return ipAddress; }
        }
	

        private bool reviewed;
        public bool Reviewed
        {
            get { return reviewed; }
        }

        private bool reported;
        public bool Reported
        {
            get { return reported; }
        }
        private bool suspended;
        public bool Suspended
        {
            get { return suspended; }
        }

        private decimal averageVote;
        public decimal AverageVote
        {
            get { return averageVote; }
        }
	
	
        private DateTime created;
        public DateTime Created
        {
            get { return created; }
        }


        public static void Sort(List<UserPostUpload> tmp, string expression)
        {
            BaseItem.SortList(tmp, expression, new UserPostUploadComparison());
        }

        public void MarkAsUnReviewed()
        {
            this.reviewed = false;
        }

        public void Approve()
        {
            this.reviewed = true;
            this.reported = false;
            this.suspended = false;
        }

        public void Suspend()
        {
            this.reviewed = true;
            this.reported = false;
            this.suspended = true;
        }

        public void Report()
        {
            if (!this.Reviewed)
            {
                this.reported = true;
            }
        }

        private List<UserPostUploadFile> files;
        protected List<UserPostUploadFile> Files
        {
            get
            {
                if(files == null && this.Id > 0)
                {
                    files = UserPostUploadFile.GetAllByUserPostUploadId(this.Id);
                }
                return files;
            }
        }

        public UserPostUploadFile GetFile(string key)
        {
            foreach (UserPostUploadFile file in this.Files)
            {
                if (file.Key == key)
                {
                    return file;
                }
            }
            return null;
        }

        private Dictionary<string, object[]> filesToSave;
        public void SetFile(string key, File.FileTypes fileType, System.Web.HttpPostedFile httpPostedFile, byte[] fileData)
        {
            if (filesToSave == null)
            {
                filesToSave = new Dictionary<string, object[]>();
            }
            filesToSave.Add(key, new object[]{fileType, httpPostedFile, fileData});
        }

        public void SetFile(string key, File.FileTypes fileType, string fileName, string contentType, int fileLength, System.IO.Stream fileStream)
        {
            if (filesToSave == null)
            {
                filesToSave = new Dictionary<string, object[]>();
            }
            filesToSave.Add(key, new object[] { fileType, fileName, contentType, fileLength, fileStream });
        }

        private Dictionary<string, string> textFields;
        public void SetTextValue(string key, string value)
        {
            if (textFields == null)
            {
                textFields = new Dictionary<string, string>();
            }
            textFields[key] = value;
        }

        public string GetTextValue(string key)
        {
            if (textFields != null && textFields.ContainsKey(key))
            {
                return textFields[key];
            }
            else
            {
                return null;
            }
        }


 
    }

    public class UserPostUploadComparison : BaseComparison<UserPostUpload>
    {

        public override int Compare(UserPostUpload x, UserPostUpload y)
        {
            switch (base.Field.ToLower())
            {
                case "comment":
                    return GetReturnValue(x.Comment, y.Comment);
                case "created":
                    return GetReturnValue(x.Created, y.Created);
                case "ipaddress":
                    return GetReturnValue(x.IPAddress, y.IPAddress);
                case "reported":
                    return GetReturnValue(x.Reported, y.Reported);
                case "reviewed":
                    return GetReturnValue(x.Reviewed, y.Reviewed);
                case "suspended":
                    return GetReturnValue(x.Suspended, y.Suspended);
                case "title":
                    return GetReturnValue(x.Title, y.Title);
                case "username":
                    return GetReturnValue(x.UserName, y.UserName);
                case "averagevote":
                    return GetReturnValue(x.AverageVote, y.AverageVote);
            }
            return 0;
        }
    }
}
